﻿using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Linq;

public class ViewScriptCreate : Editor
{

	/// <summary>
	/// path下的标记组件
	/// </summary>
	public class UIPathAndNGUITypeSign
	{
		public string _path;
		public List<NGUITypeSign> _typeSign;

		public UIPathAndNGUITypeSign(string path, NGUITypeSign typeSign)
		{
			_path = path;
			_typeSign.Add(typeSign);
		}
	}

	/// <summary>
	/// 全路径和新名字映射
	/// </summary>
	public class UIPathAndName
	{
		//root1/root2/btnLogin
		public string path;
		//m_btnLogin
		public List<string> newName = new List<string>();

		public UIPathAndName(string _path, string _newName)
		{
			path = _path;
			newName.Add(_newName);
		}
	}

	/// <summary>
	/// 组建缓存函数
	/// </summary>
	public class UIComponentAndFunName
	{
		public NGUIType _uiType;
		public string _funName;

		public UIComponentAndFunName(NGUIType type, string functionName)
		{
			this._uiType = type;
			this._funName = functionName;
		}
	}

	static private string m_scriptsPath = Application.dataPath + "/Scripts/View";
	/// <summary>
	/// 某个节点下的标记组件
	/// </summary>
	static List<UIPathAndNGUITypeSign> m_interactionUIList = new List<UIPathAndNGUITypeSign>();

	static Dictionary<string, List<NGUITypeSign>> m_interactionUIDic = new Dictionary<string, List<NGUITypeSign>>();
	static private readonly string m_initUIEventFunctionName = "InitUIEvent";
	static private readonly string m_varPrefix = "m_";
	static List<UIPathAndName> path2Name = new List<UIPathAndName>();
	static Dictionary<string, List<string>> path2NameDic = new Dictionary<string, List<string>>();
	static private readonly string m_tabStr = "    ";
	static Dictionary<string, int> componentNums = new Dictionary<string, int>() { };

	static private Dictionary<NGUIType, string> m_EventFunctionNameDic = new Dictionary<NGUIType, string>();
	static private Dictionary<NGUIType, string> m_cacheFunction = new Dictionary<NGUIType, string>();
	static private List<UIComponentAndFunName> m_cacheFuncationNew = new List<UIComponentAndFunName>();

	[MenuItem("GameObject/NGUITools/AddUIType/UIRoot", priority = 0)]
	static void AddUIType_UIRoot()
	{
		AddUIType(NGUIType.UIRoot);
	}

	[MenuItem("GameObject/NGUITools/AddUIType/Transform", priority = 0)]
	static void AddUIType_UITransform()
	{
		AddUIType(NGUIType.Transform);
	}

	[MenuItem("GameObject/NGUITools/AddUIType/UIPanel", priority = 0)]
	static void AddUIType_UIPanel()
	{
		AddUIType(NGUIType.UIPanel);
	}

	[MenuItem("GameObject/NGUITools/AddUIType/UIScrollView", priority = 0)]
	static void AddUIType_UIScrollView()
	{
		AddUIType(NGUIType.UIScrollView);
	}

	[MenuItem("GameObject/NGUITools/AddUIType/UIGrid", priority = 0)]
	static void AddUIType_UIGrid()
	{
		AddUIType(NGUIType.UIGrid);
	}

	[MenuItem("GameObject/NGUITools/AddUIType/UIScrollBar", priority = 0)]
	static void AddUIType_UIScrollBar()
	{
		AddUIType(NGUIType.UIScrollBar);
	}

	[MenuItem("GameObject/NGUITools/AddUIType/UITexture", priority = 0)]
	static void AddUIType_UITexture()
	{
		AddUIType(NGUIType.UITexture);
	}

	[MenuItem("GameObject/NGUITools/AddUIType/UIInput", priority = 0)]
	static void AddUIType_UIInput()
	{
		AddUIType(NGUIType.UIInput);
	}


	[MenuItem("GameObject/NGUITools/AddUIType/UISlider", priority = 0)]
	static void AddUIType_UISlider()
	{
		AddUIType(NGUIType.UISlider);
	}


	[MenuItem("GameObject/NGUITools/AddUIType/UIProgressBar", priority = 0)]
	static void AddUIType_UIProgressBar()
	{
		AddUIType(NGUIType.UIProgressBar);
	}


	[MenuItem("GameObject/NGUITools/AddUIType/UISprite", priority = 0)]
	static void AddUIType_UISprite()
	{
		AddUIType(NGUIType.UISprite);
	}

	[MenuItem("GameObject/NGUITools/AddUIType/UIButton", priority = 0)]
	static void AddUIType_UIButton()
	{
		AddUIType(NGUIType.UIButton);
	}

	[MenuItem("GameObject/NGUITools/AddUIType/UILabel", priority = 0)]
	static void AddUIType_UILabel()
	{
		AddUIType(NGUIType.UILabel);
	}

	[MenuItem("GameObject/NGUITools/CreateScripts", priority = 0)]
	static void CreateScripts()
	{
		if (Selection.gameObjects != null && Selection.gameObjects.Length >= 1)
		{
			GameObject go = Selection.gameObjects[0];
			NGUITypeSign sign = go.GetComponent<NGUITypeSign>();
			if (sign == null)
			{
				EditorUtility.DisplayDialog("错误", "选中物体并未添加UITypeSign组件！", "确认");
			}
			else
			{
				if (sign.Type == NGUIType.UIRoot)
				{
					//开始生成代码
					CreateScriptsToFile(go.transform);
				}
				else
				{
					EditorUtility.DisplayDialog("错误", "选中物体并不是UI根节点！", "确认");
				}
			}
		}
		else
		{
			EditorUtility.DisplayDialog("错误", "请先选中UI Root，再进行该操作！", "确认");
		}
	}
	[MenuItem("GameObject/NGUITools/DeleteNguiSignTypeMark(Ctrl+Z可撤销)", priority = 0)]
	static void DeleteNguiSignType()
	{
		if (Selection.gameObjects != null && Selection.gameObjects.Length >= 1)
		{
			GameObject go = Selection.gameObjects[0];
			NGUITypeSign[] signs = go.GetComponentsInChildren<NGUITypeSign>();
			for (int i = signs.Count()-1; i>=0 ; i--)
			{
				Debug.LogFormat("<color=red>name:{0} type:{1}</color>",signs[i].name,signs[i].Type);
                Undo.DestroyObjectImmediate((Object)signs[i]);
				DestroyImmediate(signs[i], true);
			}
		}
		AssetDatabase.Refresh();
		AssetDatabase.SaveAssets();
    }

	/// <summary>
	/// 组建添加UI代码生成标记
	/// </summary>
	/// <param name="type"></param>
	static void AddUIType(NGUIType type)
	{
		if (Selection.gameObjects != null && Selection.gameObjects.Length >= 1)
		{
			int count = Selection.gameObjects.Length;
			for (int i = 0; i < count; i++)
			{
				GameObject go = Selection.gameObjects[i];
				NGUITypeSign cacheTypeSign = go.GetComponent<NGUITypeSign>();
				if (cacheTypeSign != null)
				{
					if (cacheTypeSign.Type == type)
					{
						Debug.LogError("Transform already has the same component!!!");
						return;
					}
				}
				NGUITypeSign sign = go.AddComponent<NGUITypeSign>();

				switch (type)
				{
					case NGUIType.UIRoot:
						sign.Type = NGUIType.UIRoot;
						break;
					case NGUIType.Transform:
						sign.Type = NGUIType.Transform;
						break;
					case NGUIType.UIPanel:
						sign.Type = NGUIType.UIPanel;
						break;
					case NGUIType.UIScrollView:
						sign.Type = NGUIType.UIScrollView;
						break;
					case NGUIType.UIGrid:
						sign.Type = NGUIType.UIGrid;
						break;
					case NGUIType.UIScrollBar:
						sign.Type = NGUIType.UIScrollBar;
						break;
					case NGUIType.UITexture:
						sign.Type = NGUIType.UITexture;
						break;
					case NGUIType.UIInput:
						sign.Type = NGUIType.UIInput;
						break;
					case NGUIType.UISlider:
						sign.Type = NGUIType.UISlider;
						break;
					case NGUIType.UIProgressBar:
						sign.Type = NGUIType.UIProgressBar;
						break;
					case NGUIType.UISprite:
						sign.Type = NGUIType.UISprite;
						break;
					case NGUIType.UIButton:
						sign.Type = NGUIType.UIButton;
						break;
					case NGUIType.UILabel:
						sign.Type = NGUIType.UILabel;
						break;
					default:
						break;
				}
			}
		}
	}

	static void CreateScriptsToFile(Transform root)
	{
		if (root == null)
		{
			return;
		}

		InitConponentRef();
		m_interactionUIList.Clear();
		m_interactionUIDic.Clear();
		GetUITypeSignDic(root, "");

		string scriptName = root.name;
		StringBuilder sb = new StringBuilder();
		sb.AppendLine("using UnityEngine;");
		sb.AppendLine("using UnityEngine.UI;");
		sb.AppendLine("using System;");
		sb.AppendLine();
		sb.Append("public class ");
		sb.Append(scriptName);
		sb.Append(" : MonoBehaviour");
		sb.AppendLine();
		sb.AppendLine("{");

		sb.Append(m_tabStr);
		sb.AppendLine("#region 此代码为自动生成,谨慎改动(@Author:wuzhang)");
		int count = 0;
		if (m_interactionUIDic != null && m_interactionUIDic.Count > 0)
		{
			foreach (var item in m_interactionUIDic)//path
			{
				foreach (var typeSingn in item.Value)//List<TypeSign>
				{
					string typeName = GetStrByUIType(typeSingn.Type);
					if (!string.IsNullOrEmpty(typeName))
					{
						if (componentNums.ContainsKey(typeName))
						{
							count = componentNums[typeName]++;
						}
						StringBuilder sb_variable = new StringBuilder();
						sb_variable.Append("private ");
						sb_variable.Append(typeName);
						sb_variable.Append(" ");
						sb_variable.Append(m_varPrefix);//变量名前缀
						string name = null;
						//多层路径，解析到最后一层
						if (item.Key.Contains("/"))
						{
							int index = item.Key.LastIndexOf("/");
							name = typeName.Substring(2) + "_" + item.Key.Substring(index + 1) + (count > 0 ? "_" + count.ToString() : "");
						}
						else
						{
							name = item.Key;
						}
						//保存变量名，以path为key
						UIPathAndName path2NameTmp = new UIPathAndName(item.Key, m_varPrefix + name);
						if (!path2Name.Contains(path2NameTmp))
							path2Name.Add(path2NameTmp);

						if (!path2NameDic.ContainsKey(item.Key))
						{
							List<string> comNames = new List<string>();
							comNames.Add(m_varPrefix + name);
							path2NameDic.Add(item.Key, comNames);
						}
						else
						{
							path2NameDic[item.Key].Add(m_varPrefix + name);
						}
						sb_variable.Append(name);
						sb_variable.Append(" = null;");
						sb.Append(m_tabStr);
						sb.AppendLine(sb_variable.ToString());
					}
				}

			}
		}
		sb.AppendLine();

		sb.Append(m_tabStr);
		sb.Append("private bool isInit = false; ");
		sb.AppendLine();

		//插入Awake函数
		sb.AppendLine(m_tabStr);
		sb.Append(m_tabStr);
		sb.Append("void Awake()");
		sb.AppendLine(m_tabStr);
		sb.Append(m_tabStr);
		sb.Append("{");
		sb.AppendLine();
		sb.Append(m_tabStr);
		sb.Append(m_tabStr);
		sb.Append("InitUIComponent();");
		sb.Append("");
		sb.AppendLine();
		sb.Append(m_tabStr);
		sb.Append("}");
		sb.AppendLine();

		//插入InitUIComponent函数
		sb.AppendLine(m_tabStr);
		sb.Append(m_tabStr);

		sb.AppendLine("void InitUIComponent()");
		sb.Append(m_tabStr);
		sb.Append("{");
		sb.AppendLine();

		sb.Append(m_tabStr);
		sb.Append(m_tabStr);
		sb.Append("if (isInit)");
		sb.AppendLine();
		sb.Append(m_tabStr);
		sb.Append(m_tabStr);
		sb.Append(m_tabStr);
		sb.Append("return;");
		sb.AppendLine();
		sb.Append(m_tabStr);
		sb.Append(m_tabStr);
		sb.Append("isInit = true;");
		sb.AppendLine();

		//插入UI变量的FindChild
		if (m_interactionUIDic != null && m_interactionUIDic.Count > 0)
		{
			foreach (var item in m_interactionUIDic)//path->list<TypeSign>
			{
				for (int i = 0; i < item.Value.Count; i++)//遍历List<TypeSign>
				{
					sb.Append(m_tabStr);
					if (path2NameDic.ContainsKey(item.Key))
					{
						sb.Append(m_tabStr);
						string varName = path2NameDic[item.Key][i];// path2Name.Where(s => s.path == item._path).FirstOrDefault().newName;
						sb.Append(varName);
						sb.Append(" = transform.FindChild(");
						sb.Append("\"");
						sb.Append(item.Key);
						sb.Append("\").GetComponent<");
						sb.Append(GetStrByUIType(item.Value[i].Type));
						sb.AppendLine(">();");
					}
				}
			}
		}
		sb.Append(m_tabStr);
		sb.Append(m_tabStr);
		sb.AppendLine(m_initUIEventFunctionName + "();");//注册点击事件
		sb.Append(m_tabStr);
		sb.AppendLine("}");

		//插入start函数
		sb.AppendLine();
		sb.Append(m_tabStr);
		sb.AppendLine("void Start()");
		sb.Append(m_tabStr);
		sb.AppendLine("{");
		sb.Append(m_tabStr);
		sb.AppendLine("");
		sb.Append(m_tabStr);
		sb.AppendLine("}");

		//插入InitUIEvent函数
		sb.AppendLine();
		sb.Append(m_tabStr);
		sb.Append("private ");
		sb.Append("void ");
		sb.Append(m_initUIEventFunctionName);
		sb.AppendLine("()");
		sb.Append(m_tabStr);
		sb.AppendLine("{");
		m_cacheFunction.Clear();
		m_cacheFuncationNew.Clear();
		foreach (var item in m_interactionUIDic)
		{
			foreach (var item1 in item.Value)
			{
				if (item1.Type == NGUIType.UIButton)
				{
					sb.Append(m_tabStr);
					sb.Append(m_tabStr);
					sb.Append("UIEventListener.Get(");
					foreach (var item2 in path2NameDic[item.Key])
					{
						if (-1 != item2.IndexOf("Butt"))
						{
							string name = item2;
							sb.Append(name);
							sb.Append(".gameObject).onClick = On" + item2 + "Click;");
							sb.AppendLine();
							m_cacheFuncationNew.Add(new UIComponentAndFunName(item1.Type, "On" + item2 + "Click"));
							break;
						}
					}
				}
			}
		}
		sb.Append(m_tabStr);
		sb.AppendLine("}");

		//插入缓存的函数名
		if (m_cacheFuncationNew != null && m_cacheFuncationNew.Count > 0)
		{
			foreach (var item in m_cacheFuncationNew)
			{
				sb.AppendLine();
				sb.Append(m_tabStr);
				sb.Append("private ");
				sb.Append("void ");
				sb.Append(item._funName);
				sb.Append("(");

				//参数
				switch (item._uiType)
				{
					case NGUIType.UIInput:
						sb.Append("string arg0");
						break;
					case NGUIType.UIScrollView:
					case NGUIType.UISlider:
					case NGUIType.UIScrollBar:
						sb.Append("bool arg0");
						break;
					case NGUIType.UIButton:
						sb.Append("GameObject go");
						break;
				}
				sb.AppendLine(")");
				sb.Append(m_tabStr);
				sb.AppendLine("{");
				sb.Append(m_tabStr); sb.Append(m_tabStr);
				sb.AppendLine("throw new NotImplementedException();");
				sb.Append(m_tabStr);
				sb.AppendLine("}");
			}
		}
		sb.Append(m_tabStr);
		sb.AppendLine("#endregion");
		sb.AppendLine("}");
		WriteStrToFile(sb.ToString(), m_scriptsPath, scriptName);

		//刷新资源
		AssetDatabase.Refresh();
	}

	static void GetUITypeSignDic(Transform root, string path)
	{
		if (root == null)
		{
			return;
		}
		//支持节点多个UIType组件
		NGUITypeSign[] signs = root.GetComponents<NGUITypeSign>();

		for (int i = 0; i < signs.Length; i++)
		{
			if (signs[i] != null && signs[i].Type != NGUIType.UIRoot)
			{
				if (!m_interactionUIDic.ContainsKey(path))
				{
					//Debug.LogError(path);
					List<NGUITypeSign> typeSign = new List<NGUITypeSign>();
					typeSign.Add(signs[i]);
					m_interactionUIDic[path] = typeSign;
				}
				else
				{
					//Debug.LogError("contain "+path +" update value");
					m_interactionUIDic[path].Add(signs[i]);
				}
			}
		}

		if (root.childCount > 0)
		{
			for (int i = 0; i < root.childCount; i++)
			{

				GetUITypeSignDic(root.GetChild(i), string.IsNullOrEmpty(path) ? root.GetChild(i).name : path + "/" + root.GetChild(i).name);
			}
		}
		return;
	}

	/// <summary>
	/// 返回UI Type
	/// </summary>
	/// <param name="type"></param>
	/// <returns></returns>
	static string GetStrByUIType(NGUIType type)
	{
		string str = null;
		switch (type)
		{
			case NGUIType.UIRoot:
				str = "UIRoot";
				break;
			case NGUIType.Transform:
				str = "Transform";
				break;
			case NGUIType.UIPanel:
				str = "UIPanel";
				break;
			case NGUIType.UIScrollView:
				str = "UIScrollView";
				break;
			case NGUIType.UIGrid:
				str = "UIGrid";
				break;
			case NGUIType.UIScrollBar:
				str = "UIScrollBar";
				break;
			case NGUIType.UITexture:
				str = "UITexture";
				break;
			case NGUIType.UIInput:
				str = "UIInput";
				break;
			case NGUIType.UISlider:
				str = "UISlider";
				break;
			case NGUIType.UIProgressBar:
				str = "UIProgressBar";
				break;
			case NGUIType.UISprite:
				str = "UISprite";
				break;
			case NGUIType.UIButton:
				str = "UIButton";
				break;
			case NGUIType.UILabel:
				str = "UILabel";
				break;
			default:
				break;
		}
		return str;
	}

	static void WriteStrToFile(string txt, string path, string fileName)
	{
		if (string.IsNullOrEmpty(txt) || string.IsNullOrEmpty(path))
		{
			return;
		}
		if (!Directory.Exists(path))
			Directory.CreateDirectory(path);
		File.WriteAllText(path + "/" + fileName + ".cs", txt, Encoding.UTF8);
		Debug.LogFormat("<color=yellow>View Code Generate Finished!</color>");
	}

	static void InitConponentRef()
	{
		componentNums.Clear();
		componentNums.Add("UIRoot", 0);
		componentNums.Add("Transform", 0);
		componentNums.Add("UIPanel", 0);
		componentNums.Add("UIGrid", 0);
		componentNums.Add("UIScrollBar", 0);
		componentNums.Add("UITexture", 0);
		componentNums.Add("UIInput", 0);
		componentNums.Add("UISlider", 0);
		componentNums.Add("UIProgressBar", 0);
		componentNums.Add("UISprite", 0);
		componentNums.Add("UIButton", 0);
		componentNums.Add("UILabel", 0);
	}

	/// <summary>
	/// 根据类别和变量名返回事件函数名
	/// </summary>
	/// <param name="type">类别</param>
	/// <param name="varName">变量名</param>
	static string GetFunctionNameByTypeVarName(NGUIType type, string varName)
	{
		if (string.IsNullOrEmpty(varName))
		{
			return null;
		}
		if (!m_EventFunctionNameDic.ContainsKey(type))
		{
			return null;
		}
		string eventStr = m_EventFunctionNameDic[type];
		//这里的命名规范是On + varName + eventName
		//举例：type = UIType.Button,varName = CloseBtn，结果是OnCloseBtnClick
		return "On" + varName + eventStr.Substring(2);//截掉eventStr开头的on
	}

}
